import Vue from 'vue'
import Vuex from 'vuex'
import api from '../api/'
import {initEditor} from '../editor/'
import {
    loading,
    closeLoading,
    Observer,
    toLowerCaseObjKey,
    throttle,
    isUndefined,
    scrollToScreen,
    getCurTime,
    Resize
} from '../core/util'
import { Message } from 'element-ui'
import {START_CODE, SUCC_CODE} from '../core/constant'
import eRes from '../../core/editorRes'

Vue.use(Vuex);

const state = {
    // 文字标题
    title: window.title,
    // 文章字数
    contentLegth: 0,
    // 树状的大纲目录
    catalogList: [],
    // 当前目录索引
    curIndex: null,
    // 引用信息列表
    quoteList: [],
    // 素材库来源列表
    materialList: [],
    // 目录显隐
    // catalogVisible: false,
    // 右边栏的显隐
    rightBarVisible: false,
    // 右边栏目前显示的是哪个资源库 prep scho cnki book
    currShowingResoLib: "",
    // 保存信息
    saveMsg: `最近保存：${getCurTime()}`,
    isShowSaveIcon: false, // 是否展示正在保存的gif
    objTencentUp: {},  // 腾讯云点播的上传对象
    showUploadQueue: false, // 是否展示上传的队列弹窗
    objUploadQueue: {}, // 上传队列对象
    resize: null,
    maxUploadQueue: true, // 上传队列弹窗最大化
};

const confirmOpt = {
    confirmButtonText: '确定',
    confirmButtonClass: 'confirm-btn',
    cancelButtonText: '取消',
    cancelButtonClass: 'cancel-btn',
    type: 'warning'
};

const getters = {};

const mutations = {
    // 设置目录显隐
    triggerCatalog(state, status) {
        state.catalogVisible = status;
    },
    // 设置右边栏显隐
    triggerRightBar(state, status) {
        state.rightBarVisible = status;
        if(status === true){
            // 右侧栏显示，resize控件显示，编辑区位置偏移
            state.resize.showController();
            state.resize.changeLeftArea('afterRightOpen');
        } else {
            // 右侧栏隐藏，resize控件隐藏，编辑区位置偏移
            state.resize.hideController();
            state.resize.changeLeftArea('afterRightClose');
        }
    },
    // 设置右边栏当前展示库，type为prep
    // scho
    // cnki
    // book
    setCurrShowingResoLib(state, type){
        state.currShowingResoLib = type;
    },
    /**
     * 右边栏变动中仿真书的相关操作
     */
    fireEBookChange(state) {
        if (state.rightBarVisible && state.currShowingResoLib === 'book') { // 仿真书显示
            let book = $("#flipbook");
            if (book && typeof book.turn === "function" && book.turn("is")){
                // 仿真书已经渲染过了
            }else{
                // 仿真书未渲染
                Observer.fire("refreshBook"); // 刷新仿真书内容
            }
        }
    },
    // 设置字数
    setContentLength(state, length) {
        state.contentLegth = length;
    },
    // 设置大纲列表
    setCatalogList(state, list) {
        state.catalogList = list;
    },
    // 设置引用信息列表
    setQuoteList(state, list) {
        state.quoteList = list;
    },
    // 设置素材库来源列表
    setMaterialList(state, list) {
        state.materialList = list;
    },
    // 设置当前目录索引
    setCurIndex(state, index) {
        state.curIndex = index;
        let all = $('.wid97'),
            catalog = $('#catalog'),
            p;
        if (index === 'quoteList') {
            p = all.last();
        } else {
            p = all.eq(index);
        }
        scrollToScreen(p, catalog);
    },
    // 聚焦编辑器
    focus(state) {
        UE.getEditor('editor').focus();
    },
    // 设置保存消息
    setSaveMsg(state, msg) {
        state.saveMsg = `最近保存：${msg}`;
    },
    // 显示隐藏保存icon
    setSaveIcon(state, flag) {
        state.isShowSaveIcon = flag;
    },
    // 设置文件名
    setFileName(state, filename) {
        state.title = filename;
    },
    // 设置腾讯云上传数组
    setTencentUp(state, obj) {
        state.objTencentUp = Object.assign({}, obj);
    },
    // 生成resize对象
    initResize(state, config){
        state.resize = new Resize(config);
        state.resize.init();
    },
    // 职教库iframe插入编辑器
    insertZJ(state, {src, title, resoType}){
        let iconType = resoType == "图书" ? "ZJ_book"
          : resoType == "视频" ? "ZJ_video"
            : resoType == "国家职业技能标准" ? "ZJ_prostd"
              : '';
        eRes.addResource({
            type: 'stdIframe',
            name: title,
            ifrSrc: src,
            iconType: iconType
        });
    },
    // 上传队列的弹窗toggle
    toggleUploadQueuePop(state, flag){
        if(flag === true){
            // 要打开队列时，最大化
            state.maxUploadQueue = true;
        }
        state.showUploadQueue = flag;
    },
    // 上传队列的最大化最小化
    maxMinUploadQueue(state, flag){
        if(flag === "max"){
            state.maxUploadQueue = true;
        }else if(flag === "min"){
            state.maxUploadQueue = false;
        }
    },
    // 设置上传队列的数组
    setUploadQueue(state, obj){
        state.objUploadQueue = Object.assign({}, obj);
    },
    // 更新上传队列的进度
    updateUploadQueue(state, obj){
        state.objUploadQueue[obj.rdmKey].percentage = obj.percentage;
    }
};

const actions = {
    /**
     * 初始化编辑器，在EditArea.vue里被调用
     */
    init({commit}) {
        api.initEditorContent().then(({content, title, resourceCode}) => {
            let editor = initEditor(content);
            window.editorId = 'editor';
            commit("setFileName", title);
            window.rcForKT = resourceCode; // 给课题用的resourcecode
        }).catch((type) => {
            // 初始化失败
            Message({
                message: '初始化编辑器失败！',
                type: 'error'
            });
            console.log("检查接口，检查登录状态！！！");
            console.log("检查接口，检查登录状态！！！");
            console.log("检查接口，检查登录状态！！！");
            if(process.env.NODE_ENV === "development" && type === "openLogin"){
                window.open("http://192.168.107.77/sso/login?appid="+window.apiurl+"_local", "_blank");
            }
        });
    },
    // 保存
    save({dispatch, commit, state}) {
        dispatch('saveContent').then(() => {
            commit("setSaveMsg", getCurTime());
            // 如果仿真书在打开，刷新仿真书
            if (state.rightBarVisible && state.currShowingResoLib === 'book') { // 仿真书显示
                Observer.fire("refreshBook");
            }
        }).catch(() => {
            Message({
                message: '保存失败',
                type: 'error'
            })
        });
    },
    // 保存内容
    saveContent({commit}, content) {
        commit('setSaveIcon', true); // 显示保存icon
        let editor = UE.getEditor(window.editorId);
        if (isUndefined(content)) {
            content = editor.getContent();
        }
        // editor.focus();
        return api.saveContent().then(() => {
            lastContent = content;
            setTimeout(() => commit('setSaveIcon', false), 1500)   // 隐藏保存icon
        }, () => {
            setTimeout(() => commit('setSaveIcon', false), 1500)   // 隐藏保存icon
        }).catch(err => {
            console.log(err);
        });
    },
    // 提交
    submit({dispatch}, content) {
        loading(true);
        dispatch('saveContent').then(() => {
            closeLoading();
            Message({
                message: '保存成功',
                type: 'success'
            });
        }).catch(() => {
            closeLoading();
            Message({
                message: '保存失败',
                type: 'error'
            });
        });
    },
    // 打开素材库显示文章
    // openMaterial({commit}, data) {
    //     commit('triggerMaterial', true);
    //     Observer.fire('openMaterial', data);
    // },
    // 滚动事件
    scroll({commit}, event) {
        selectionchange(UE.getEditor('editor'));
    },
    // 滚动至对应索引
    scrollTo({commit}, index) {
        let editor = UE.getEditor('editor');
        let editArea = $('#editArea'),
            iframe = $(editor.iframe),
            tag,
            scrollTop;
        if (index === 'quoteList') {
            scrollTop = $(`#${index}`).offset().top - editArea.offset().top + editArea.scrollTop();
        } else {
            tag = iframe.contents().find(`:header:eq(${index})`);
            scrollTop = tag.offset().top + iframe.offset().top - editArea.offset().top + editArea.scrollTop();
        }
        editArea.animate({
            scrollTop: scrollTop
        }, 'fast', () => {
            if (tag) {
                let range = editor.selection.getRange();
                range.setStartAtFirst(tag.get(0)).trimBoundary().collapse(true);
            }
            editor.focus();
            commit('setCurIndex', index);
        });
    },
    // 导出
    export({dispatch}, type) {
        loading(true);
        api.export(type).then((taskId) => {
            dispatch('queryStatus', taskId);
        }).catch((e) => {
            closeLoading();
            Message({
                message: '导出失败',
                type: 'error'
            });
            console.log(e);
        })
    },
    // 查询状态并下载
    queryStatus({state, dispatch}, taskId) {
        api.queryStatus(taskId, state.title).then(({StatusCode, TargetFileName}) => {
            console.log(StatusCode);
            // console.log(TargetFileName);
            if (StatusCode === SUCC_CODE) {
                closeLoading();
                let a = document.createElement('a');
                a.style.display = 'none';
                document.body.appendChild(a);
                a.href = TargetFileName;
                a.click();
                document.body.removeChild(a);
            } else if (StatusCode >= START_CODE && StatusCode < SUCC_CODE) {
                setTimeout(() => {
                    dispatch('queryStatus', taskId);
                }, 5 * 1000);
            } else {
                closeLoading();
                Message({
                    message: '导出失败',
                    type: 'error'
                });
                console.log(`StatusCode:${StatusCode}`);
            }
        }).catch(e => {
            closeLoading();
            Message({
                message: '查询导出状态失败',
                type: 'error'
            });
            console.log(e);
        });
    },
    /**
     * 添加职教库资源
     */
    addZJData({commit}, data){
        let count = data.length; // 计数器
        let onceLoading = true;
        for(let item of data) {
            if(onceLoading){
                loading(true);
                onceLoading = false;
            }
            axios.get(globalVar.cnkiFullTextAddr + "/help/cnki/vefulltext",{
                params: {
                    dbCode: (item.TableName || "").substring(0, 4).toUpperCase(),
                    fileName: item.FileName || "",
                    tableName: item.PhysicalTableName || "",
                    userId: dataFromFather.userID,
                    Id: item.Id,
                    format: item.Format || ''
                }
            }).then(res => {
                if (res && res.data && res.data.Code === 200) {
                    var num = Math.random(0, 5).toFixed(5);
                    let src = res.data.Data ? res.data.Data + "&version=" + num : "";
                    // console.log(src);
                    let title = item.Title.replace(/<span.*?>(.*?)<\/span>/g, '$1');
                    commit('insertZJ', {src, title, resoType: item.resourceType});
                } else {
                    Message({
                        message: '查询职教库地址出错！',
                        type: 'error'
                    });
                }
                count--;
                if(count === 0){
                    closeLoading();
                }
            }).catch(err => {
                console.log(err);
                Message({
                    message: '查询职教库地址出错！',
                    type: 'error'
                });
                count--;
                if(count === 0){
                    closeLoading();
                }
            });
        }
    },
    /**
     * 知网资源添加图片
     */
    addCnkiImg({commit}, data) {
        let value = "";
        for (var i = 0; i < data.length; i++) {
            value += `<p style="text-align: center;margin-bottom: 0;"><img src="${data[i].Src}" role="999"></p>
                <p style="margin-top: 0; color: #1391FF; text-align: center;font-size: 12px;">${data[i].Name || ""}</p>`;
        }
        Observer.fire("insertHtml", value);
    },
    /**
     * 关闭编辑器
     */
    closeEditor() {
        window.parent.postMessage("closeEditor", "*");
    },
    /**
     * 添加到统计
     * 检索、查看、引用
     */
    addStatistics({commit}, optType){
        if(process.env.NODE_ENV === 'development') return; // 测试环境
        axios.post("/api/log/Action",qs.stringify({
            objCode: dataFromFather.courseCode, // courseCode
            resourceCode: dataFromFather.catalogCode, // catalogCode
            operationType: optType // 知网资源查询18 知网资源引用19 本校资源查询33 本校资源引用34
        })).then(res => {
            // console.log(res);
        }).catch(err => {
            console.log(err);
            Message({
                message: '添加统计数据失败!',
                type: 'error'
            });
        })
    }
};

const store = new Vuex.Store({
    state,
    getters,
    mutations,
    actions
});

// 字数变化
// modified by lyu on 2019/05/30 没有文字时设置默认行高
Observer.register('contentchange', (editor) => {
    var textCount = editor.getContentTxt().length;
    store.commit('setContentLength', textCount);
});

// 参考文献变化
Observer.register('contentchange', throttle((editor) => {
    if (!editor.isReady) return;
    let array = UE.dom.domUtils.getElementsByTagName(editor.document, 'sup', function (node) {
            return node.hasAttribute('data-quote')
        }),
        index = 1,
        supList = [],
        map = {};
    for (let i = 0, len = array.length; i < len; i++) {
        //如果引用信息符合格式则重新排序，否则删除引用信息
        if (/^\[\d+]$/.test(array[i].innerHTML)) {
            let content = array[i].getAttribute('data-quote');
            if (map[content]) {
                // 如果引用信息重复则使用原来的值
                array[i].innerHTML = array[i].innerHTML.replace(/\d+/g, map[content] + '');
            } else {
                // 否则设置引用信息的index并将其放入map中
                array[i].innerHTML = array[i].innerHTML.replace(/\d+/g, index + '');
                map[content] = index++;
                supList.push({
                    title: array[i].innerHTML,
                    content: content
                });
            }
            array[i].setAttribute('contenteditable', false);
        } else {
            array[i].removeAttribute('contenteditable');
            array[i].removeAttribute('data-quote');
        }
    }
    store.commit('setQuoteList', supList);
}), 200);

// 素材库来源信息改变
Observer.register('contentchange', throttle(function (editor) {
    if (!editor.isReady || window.isPSMC) return;
    let domUtils = UE.dom.domUtils;
    let dom = editor.document;
    let array = domUtils.getElementsByTagName(dom, 'sup', (node) => {
        return !!node.getAttribute('data-info');
    });
    let map = {}, // 用于存储每个p标签所对应的对象key为nodeList的第index个
        nodeList = [], // 存储已遇到过的dom对象
        list = []; // 所有含有引用的节点
    for (let i = 0, len = array.length; i < len; i++) {
        let node = domUtils.findParentByTagName(array[i], ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'table']), // 找到sup标签所在p标签算取高度
            index,
            info = array[i].getAttribute('data-info'),
            dataInfo = toLowerCaseObjKey(JSON.parse(unescape(info)));
        // 查看dom节点是否在nodeList列表中出现过
        if ((index = nodeList.indexOf(node)) === -1) {
            index = nodeList.length;
            map[index] = {
                offsetTop: node.offsetTop, // p标签所在高度
                list: [], // 每个p标签的引用列表
                map: {}   // 去重对象
            };
            nodeList.push(node);
            list.push(map[index]);
        }
        // 判断当前引用信息是否在当前p标签内存在，如有则不添加
        if (!map[index].map[info]) {
            map[index].map[info] = true;
            map[index].list.push(dataInfo);
        }
    }
    store.commit('setMaterialList', list);
}, 200));

// 大纲目录变化
let original = [];
Observer.register('contentchange', (editor) => {
    function traversal(section) {
        let res = [];
        for (let i = 0, len = section.length; i < len; i++) {
            let obj = {};
            obj.title = section[i].title;
            obj.i = index++;
            obj.children = traversal(section[i].children);
            obj.extensionLine = section[i].tag.replace(/\D/g, '') - (section[i].parentSection.tag.replace(/\D/g, '') || 0) - 1;
            res.push(obj);
        }
        return res;
    }

    let now = $(editor.iframe).contents().find(':header').map(function (i, item) {
            return item.outerHTML;
        }),
        change = false,
        arr, index = 0;
    if (now.length === original.length) {
        for (let i = 0, len = now.length; i < len; i++) {
            if (now[i] !== original[i]) {
                change = true;
                break;
            }
        }
    } else {
        change = true;
    }
    if (change) {
        original = now;
        store.commit('setCatalogList', traversal(editor.execCommand('getsections').children));
    }
});

// 选区变化或滚动条变化修改当前目录索引
let lastRangeOffset;
const selectionchange = throttle((editor) => {
    try {
        let range = editor.window.getSelection().getRangeAt(0),
            editArea = $('#editArea'),
            bottomHeight = $('.edit-footer').height(),
            iframe = $(editor.iframe),
            head = iframe.contents().find(":header"),
            rangeOffset = range.getBoundingClientRect();
        // console.log(rangeOffset, bottomHeight);
        // 选区xy为0时使用上一次的选区位置
        if (!rangeOffset.x && !rangeOffset.y) {
            rangeOffset = lastRangeOffset;
        } else {
            lastRangeOffset = rangeOffset;
        }
        // 判断在顶部之下和底部之上
        let isUnderTop = (rangeOffset.top + iframe.offset().top - editArea.offset().top + rangeOffset.height) >= 0,
            isAboveBottom = (rangeOffset.top + iframe.offset().top - editArea.offset().top) <= (editArea.outerHeight() + bottomHeight),
            index = null;
        // 在屏幕中
        if (isUnderTop && isAboveBottom) {
            let node = UE.dom.domUtils.findParentByTagName(range.startContainer, ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'table'], true);
            // 找到该段落所在的标题
            while (!/^h\d+$/i.test(node.tagName.toLowerCase()) && node.previousSibling) {
                node = node.previousSibling;
            }
            for (let i = 0, len = head.length; i < len; i++) {
                if (head[i] === node) {
                    index = i;
                    break;
                }
            }
        } else {
            // 找到最后一个出现在屏幕中的标题
            for (let i = head.length - 1; i >= 0; i--) {
                if (head.eq(i).offset().top + iframe.offset().top - editArea.offset().top <= editArea.outerHeight()) {
                    index = i;
                    break;
                }
            }
            let quoteList = $('#quoteList');
            if (quoteList.length && quoteList.css('display') !== 'none' && quoteList.offset().top - editArea.offset().top <= editArea.outerHeight()) {
                index = 'quoteList';
            }
        }
        store.commit('setCurIndex', index);
    } catch (e) {

    }
}, 100);
Observer.register('selectionchange', selectionchange);

// 保存和自动保存
let lastContent;
let saveTimer;
Observer.register('editorCompleted', (editor) => {
    lastContent = editor.getContent();
});
Observer.register('saveContent', (editor) => {
    store.dispatch('save');
});
Observer.register('contentchange', (editor) => {
    clearTimeout(saveTimer);
    saveTimer = setTimeout(() => {
        let content = editor.getContent();
        if (lastContent !== content) {
            store.dispatch('saveContent', content).then(() => {
                store.commit("setSaveMsg", getCurTime());
            }).catch(() => {
                Message({
                    message: '自动保存失败',
                    type: 'error'
                });
            });
        }
    }, 5 * 1000);
});

// 注册添加参考文献事件
Observer.register('insertHtml addText', function (data) {
    if (window.editorId) {
        //获取当前编辑器对象
        var editor = UE.getEditor(window.editorId);
        //在编辑器中插入内容
        if (typeof data === 'string') {
            editor.execCommand("inserthtml", data);
        } else {
            editor.execCommand("inserthtml", data.html);
            if (data.quote) {
                editor.focus();
                editor.execCommand('insertquote', {
                    quote: data.quote,
                    info: data.info
                });
            }
        }
        editor.execCommand("autoadjustheight");
        setTimeout(function () {
            editor.focus();
        }, 10);
    } else {
        Message({
            message: $.i18n('messager_need_to_focus'),
            type: 'warning'
        });
    }
});
export default store
